package com.cskaoyan.javase.oop3._0abstract._1basic;

/**
 * 抽象类的定义：
 * 在继承体系中，从祖先类开始，随着一个个子类的定义，子类变得越来越具体，
 * 而祖先类则更具有一般性和抽象性。
 * 在这种情况下，为了体现祖先类在设计上的抽象性，我们只将该类作为派生其他类的父类，
 * 而不能创建对象实例。这个时候，这样的类，我们称之为抽象类。
 *
 * 总结：抽象类是作为继承层次中的祖先类而存在的。
 * 所以在开发中，想要定义抽象类，就要考虑它是不是继承层次中的祖先类
 * 如果是就定义抽象类,如果不是就不要滥用抽象类
 * 抽象类也是类,它和它的子类也是使用extends关键字,也是继承关系,和子类也是"is-a"关系
 *
 * 自此，我们已经引入了抽象类的概念。
 * 接下来，我们重点来研究一个抽象类的特点和使用。
 * 抽象类的特点我们主要从以下角度：
 * [修饰符列表] abstract class 类名{
 *     //类体
 * }
 * 1.抽象类名命名特点
 *      抽象类的命名建议以"Base"或者"Abstract"开头
 *      比如一个抽象的人类,就叫"BasePerson"或者"AbstractPerson"
 *      这种写法就可以让人一眼看成该类是抽象类
 *
 * 2.抽象类定义时能用哪些修饰符？
 *      访问权限修饰符肯定是可以用的
 *      抽象类不能用final修饰,因为final阻止继承,但抽象类定义出来就是为了继承的
 *
 * 3.抽象类的成员特点
 *      抽象类中可以定义普通类中能够定义的普通成员以及静态成员
 *      抽象类中有没有构造器呢?
 *      首先抽象类是不能创建对象的,但是构造器的作用也并不是创建对象
 *      抽象类是存在构造器的,抽象类的构造器是给子类对象初始化用的,给子类用的.
 *      扩展: Java中所有的类,任何类都有构造器.这句话是正确的.
 *      抽象类中能够定义代码块吗? 既然有构造器就有构造代码块,既然能写静态成员变量就有静态代码块
 *
 *      以上总结: 普通类中能够定义的结构,抽象类中也同样能够定义
 *
 *      思考:
 *          1.Java的一个类,如果不考虑创建它的对象,那么直接声明为abstract会报错吗?
 *              是不会报错的,原因是普通类中能够定义的结构,抽象类中也同样能够定义
 *          2.抽象类能够继承普通类吗?
 *              能够继承,原因是普通类中能够定义的结构,抽象类中也同样能够定义
 *              事实上,一个抽象类如果没有直接声明父类,那么它仍然继承Object
 *          3.抽象类中可以没有抽象方法吗?
 *              可以的,但是抽象类如果没有抽象方法是没有意义的,抽象类就应该有抽象方法.
 *              如果想着禁止创建类的对象,而把一个类声明抽象类,这种做法是不合适的
 *              抽象类是作为继承层次中的祖先类而存在
 *              不要滥用抽象类
 *
 * 抽象类中的抽象方法:
 * 抽象方法的定义:
 * [访问权限修饰符] abstract 返回值类型 方法名(形参列表);
 * 在抽象父类中定义抽象方法
 * 这样普通子类中必须要实现这个抽象方法(实现的过程就是方法的重写)
 * 这种情况下,抽象方法就起着"占位"的作用.
 * 起着制定"标准和规范"的作用
 *
 * 综上: 抽象类其实就比普通类多了一个抽象方法的结构
 * 但是抽象类是必须要有抽象方法的,没有抽象方法的抽象类毫无意义.
 *
 * 抽象类的子类:
 *      1.普通类,必须实现抽象父类中的所有抽象方法,没得选
 *      2.抽象类,不需要强制实现抽象父类中的抽象方法了
 *          但是如果想要实现,也是可以选择实现的
 *
 *
 * @since 16:20
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        Student s = new Student(100, 200);
        System.out.println(s.a);
        System.out.println(s.getB());
    }
}

// 抽象人类
abstract class AbstractPerson {
    static {
    }

    {

    }

    int a;
    private int b = 10;
    static int c = 20;
    static final int D = 30;

    public int getB() {
        return b;
    }

    public AbstractPerson(int a, int b) {
        this.a = a;
        this.b = b;
    }

    public AbstractPerson() {
    }

    /*
                Java抽象类是允许写实现方法的
                假如有以下需求:
                    该抽象类的子类中有一个共同的行为,需要一个默认的实现
                    那就可以把这个默认实现写在抽象类中

             */
    public void test() {
    }

    public static void testStatic() {
    }

    // 定义抽象方法
    public abstract void testAbstract();

    public abstract void testAbstract2();

}

// Class 'Student' must either be declared abstract or implement abstract method 'testAbstract()' in 'AbstractPerson'
/*
    实现抽象方法建议采取以下方式:
        1.alt + 回车报错的位置(建议)
        2.alt + insert
 */
class Student extends AbstractPerson {
    public Student(int a, int b) {
        super(a, b);
    }

    public Student() {
    }

    @Override
    public void testAbstract() {
        System.out.println("我是抽象方法的实现");
    }

    @Override
    public void testAbstract2() {
        System.out.println("实现抽象方法的实现2");
    }
}

abstract class Teacher extends AbstractPerson {
    @Override
    public void testAbstract() {

    }

    @Override
    public void testAbstract2() {

    }
}
// Illegal combination of modifiers: 'final' and 'abstract'
// abstract final class AbstractPerson{
//
// }
